// This is for the charger
#include "AC-Controller.h"

// Here is the pin usage so far:


/*****************Config bit settings****************/
_FOSC(0xFFFF & XT_PLL8); // Use XT with external crystal from 4MHz to 10MHz.  FRM Pg. 178
_FWDT(WDT_ON & WDTPSA_64 & WDTPSB_1); // See Pg. 709 in F.R.M.				

_FBORPOR(0xFFFF & PWRT_64 & MCLR_EN & PWMxL_ACT_LO); // Brown Out voltage set to 2v.  Power up time of 64 ms. MCLR is enabled. PWM LOW ACT LOW.  HAHA.  IT WAS INVERTED BEFORE I GUESS.

#define dFoscExt        8000000         // External Crystal
#define dPLL            8               // PLL ratio
//#define dPWMPeriodInSec  0.000064          // PWM Period - 64 uSec, 15.625khz PWM
#define dPWMPeriodInSec  0.000128  		// PWM Period - 128 uSec, 7.8khz PWM

#define THROTTLE_MIN_RAW 413
#define THROTTLE_MAX_RAW 683
#define THROTTLE_RANGE_RAW (THROTTLE_MAX_RAW - THROTTLE_MIN_RAW)

// Derived
#define dFosc       (dFoscExt*dPLL)     // Clock frequency (Hz). dFosc = 64,000,000 in this case.
#define dFcy        (dFoscExt*dPLL/4)           // Instruction cycle frequency (Hz). dFcy = 16,000,000 in this case.
#define dTcy        (4.0/(dPLL*dFoscExt))          // Instruction cycle period (sec). 1/16,000,000 second

#define dPWMPeriodInTcy  (int)(dPWMPeriodInSec/dTcy)   // Basic loop period in units of Tcy.
//#define MAX_CURRENT_REF 2047 // (dPWMPeriodInTcy - 1) // 1023
#define MAX_THROTTLE 2047
//#define ZERO_PWM 1024
#define MAX_PWM 2047 // MAX_CURRENT_REF
#define MAX_SPEED 512
#define NUM_TICKS 1024
//volatile unsigned int voltageScaler; // Let's say maximum voltage occurs at a speed of x.  The scaler should be 0 at 0v, and "1" at a speed of 504. 1024 = "1".

// V/Hz variables //////////////////////////////////////////////
volatile long int speed_V_HZ = 0L;  // speed of 60 Hz corresponds to speed_V_HZ of 504*(2^16).  Speed of 0 Hz corresponds to speed_V_HZ of 0.  Speed of -60 Hz means speed_V_HZ of -504*(2^16).
volatile int smallSpeed_V_HZ;  // Only used in V/Hz mode.  The scaled down version of speed_V_HZ.  In range [-512, 512] or so.

volatile unsigned int positionHiResPH1;  // A circle broken up into 65536 "degrees".  Add 504 each time to positionHiResPH1 if you want to have motor speed be 60 Hz, if it's being updated at 8kHz.
volatile int sinPhase1;

volatile unsigned int positionHiResPH2;
volatile int sinPhase2;


volatile unsigned int positionHiResPH3;
volatile int sinPhase3;

// 512 possible values for sin.  for x in [-1, 1] = [-32767, 32767]
const int _sin[] =  
{0, 	402,	804,	1206,	1608,	2009,	2410,	2811,	3212,	3612,	4011,	4410,	4808,	5205,	5602,	5998,	6393,	6786,	7179,	7571,	7962,
8351,	8739,	9126,	9512,	9896,	10278,	10659,	11039,	11417,	11793,	12167,	12539,	12910,	13279,	13645,	14010,	14372,	14732,	15090,	15446,
15800,	16151,	16499,	16846,	17189,	17530,	17869,	18204,	18537,	18868,	19195,	19519,	19841,	20159,	20475,	20787,	21096,	21403,	21705,	22005,
22301,	22594,	22884,	23170,	23452,	23731,	24007,	24279,	24547,	24811,	25072,	25329,	25582,	25832,	26077,	26319,	26556,	26790,	27019,	27245,
27466,	27683,	27896,	28105,	28310,	28510,	28706,	28898,	29085,	29268,	29447,	29621,	29791,	29956,	30117,	30273,	30424,	30571,	30714,	30852,
30985,	31113,	31237,	31356,	31470,	31580,	31685,	31785,	31880,	31971,	32057,	32137,	32213,	32285,	32351,	32412,	32469,	32521,	32567,	32609,
32646,	32678,	32705,	32728,	32745,	32757,	32765,	32767,	32765,	32757,	32745,	32728,	32705,	32678,	32646,	32609,	32567,	32521,	32469,	32412,
32351,	32285,	32213,	32137,	32057,	31971,	31880,	31785,	31685,	31580,	31470,	31356,	31237,	31113,	30985,	30852,	30714,	30571,	30424,	30273,
30117,	29956,	29791,	29621,	29447,	29268,	29085,	28898,	28706,	28510,	28310,	28105,	27896,	27683,	27466,	27245,	27019,	26790,	26556,	26319,
26077,	25832,	25582,	25329,	25072,	24811,	24547,	24279,	24007,	23731,	23452,	23170,	22884,	22594,	22301,	22005,	21705,	21403,	21096,	20787,
20475,	20159,	19841,	19519,	19195,	18868,	18537,	18204,	17869,	17530,	17189,	16846,	16499,	16151,	15800,	15446,	15090,	14732,	14372,	14010,
13645,	13279,	12910,	12539,	12167,	11793,	11417,	11039,	10659,	10278,	9896,	9512,	9126,	8739,	8351,	7962,	7571,	7179,	6786,	6393,
5998,	5602,	5205,	4808,	4410,	4011,	3612,	3212,	2811,	2410,	2009,	1608,	1206,	804,	402,	0,  	-402,	-804,	-1206,	-1608,
-2009,	-2410,	-2811,	-3212,	-3612,	-4011,	-4410,	-4808,	-5205,	-5602,	-5998,	-6393,	-6786,	-7179,	-7571,	-7962,	-8351,	-8739,	-9126,	-9512,
-9896,	-10278,	-10659,	-11039,	-11417,	-11793,	-12167,	-12539,	-12910,	-13279,	-13645,	-14010,	-14372,	-14732,	-15090,	-15446,	-15800,	-16151,	-16499,	-16846,
-17189,	-17530,	-17869,	-18204,	-18537,	-18868,	-19195,	-19519,	-19841,	-20159,	-20475,	-20787,	-21096,	-21403,	-21705,	-22005,	-22301,	-22594,	-22884,	-23170,
-23452,	-23731,	-24007,	-24279,	-24547,	-24811,	-25072,	-25329,	-25582,	-25832,	-26077,	-26319,	-26556,	-26790,	-27019,	-27245,	-27466,	-27683,	-27896,	-28105,
-28310,	-28510,	-28706,	-28898,	-29085,	-29268,	-29447,	-29621,	-29791,	-29956,	-30117,	-30273,	-30424,	-30571,	-30714,	-30852,	-30985,	-31113,	-31237,	-31356,
-31470,	-31580,	-31685,	-31785,	-31880,	-31971,	-32057,	-32137,	-32213,	-32285,	-32351,	-32412,	-32469,	-32521,	-32567,	-32609,	-32646,	-32678,	-32705,	-32728,
-32745,	-32757,	-32765,	-32767,	-32765,	-32757,	-32745,	-32728,	-32705,	-32678,	-32646,	-32609,	-32567,	-32521,	-32469,	-32412,	-32351,	-32285,	-32213,	-32137,
-32057,	-31971,	-31880,	-31785,	-31685,	-31580,	-31470,	-31356,	-31237,	-31113,	-30985,	-30852,	-30714,	-30571,	-30424,	-30273,	-30117,	-29956,	-29791,	-29621,
-29447,	-29268,	-29085,	-28898,	-28706,	-28510,	-28310,	-28105,	-27896,	-27683,	-27466,	-27245,	-27019,	-26790,	-26556,	-26319,	-26077,	-25832,	-25582,	-25329,
-25072,	-24811,	-24547,	-24279,	-24007,	-23731,	-23452,	-23170,	-22884,	-22594,	-22301,	-22005,	-21705,	-21403,	-21096,	-20787,	-20475,	-20159,	-19841,	-19519,
-19195,	-18868,	-18537,	-18204,	-17869,	-17530,	-17189,	-16846,	-16499,	-16151,	-15800,	-15446,	-15090,	-14732,	-14372,	-14010,	-13645,	-13279,	-12910,	-12539,
-12167,	-11793,	-11417,	-11039,	-10659,	-10278,	-9896,	-9512,	-9126,	-8739,	-8351,	-7962,	-7571,	-7179,	-6786,	-6393,	-5998,	-5602,	-5205,	-4808,
-4410,	-4011,	-3612,	-3212,	-2811,	-2410,	-2009,	-1608,	-1206,	-804,	-402, 0, 0, 0, 0, 0, 0, 0, 0, 0};
////////////////////////////////////////////////////////////////

// Field Oriented Control variables ///////////////////////////////////////////////
volatile int i_a, i_b, i_c;		// The 3 A/D current values.  in [-128, 128].  You only need 2 of them, because i_a + i_b + i_c = 0
volatile int i_alpha, i_beta;	// Result of Clarke Transform.  in [-128, 128] or so.
volatile int i_d, i_q;			// Result of the Park Transform.  in [-128, 128] or so.
volatile unsigned int tempOffset1, tempOffset2; // in [0, 511].  Offsets for the sin lookup table.

volatile long int cos_theta, sin_theta;  // in [-(2^15), 2^15].  They are only used in long multiplications, so I was just trying to avoid having to cast them as long.
volatile long int v_d, v_q;		// These are the "duties" that I set based on the throttle position.  in [-(2^16)*749, (2^16)*749].
volatile int v_alpha, v_beta;	// Result of doing the inverse Park transform.  in [-1023, 1023].  
volatile int Vr1, Vr2, Vr3;  	// Result of doing the modified inverse Clarke transform.  in [-1023, 1023].

volatile unsigned int T1, T2;		// The times for how to share the duty between adjacent transistor switching states.  in [0, MAX_PWM/2].  T1 + T2 = MAX_PWM.
volatile unsigned int Ta, Tb, Tc;  	// The 3 duties.  In [0, MAX_PWM].

volatile int rotorSpeed;  			// Used for the AC controller in calculating the rotor flux angle.  In [-512, 512] or so.  480 corresponds to 60 Hz.  1 corresponds to about 1/8 Hz.

volatile int rotorFluxAngle; 		// This is the rotor flux angle. In [0, 1023], but may be negative during part of the calculation below.  Used in the PMSM software.
volatile unsigned int oldTickCount; // Used to find rotor speed.  For the AC controller with FOC.  in [0, 65535].
volatile unsigned int tickCount;    // Used as a temporary variable to hold POSCNT.  in [0, 65535].
volatile unsigned int rotorPos = 0; // start it out as 0, then figure out what it really is.  It will be a constant for this motor forever.  in [0, 1023].  How far past the index does the 
									// motor stop spinning when i_q = 0, and i_d is throttle.  Make sure you pass index to reset POSCNT.  Then hit the throttle.  When the post stops spinning,
									// you have found rotorPos.  i_q will have maximum affect here, since i_q is at 90 degrees to i_d.  i_d does nothing, so i_q will be perfect.
/////////////////////////////////////////////////////////////////

volatile unsigned int now, previous = 0;
volatile unsigned int faultBits = 0;

volatile int current_ramp_rate = 1;
volatile long pwm = 0;
volatile unsigned int counter_16k = 0;		// 16 KHz counter
volatile unsigned int counter_8k = 0;		// 8 KHz counter
volatile unsigned int counter_4k = 0;		// 4 KHz counter
volatile unsigned int counter_2k = 0;		// 2 KHz counter
volatile unsigned int counter_1k = 0;		// 1KHz counter for timing
volatile unsigned int counter_1sec = 0;  		// How many 2sec intervals have there been?
//volatile unsigned int start1, start2, start3;		// for keeping track of times.
//volatile unsigned int end1, end2, end3;

// CH0=AN3, CH1=AN0, CH2=AN1, CH3=AN2. 
//volatile unsigned loc_temperature2;		// AD channel 
//volatile unsigned loc_temperature1;		// AD channel 

volatile int overCurrentHasOccurred = 0;	// Has an overcurrent event occurred on at least 1 of the 3 phases? 
volatile int duty1, duty2, duty3;
volatile int throttle_feedback;			// AD channel 
volatile int throttle_average = 0;
volatile int vref = 512;			// vref should be about 2.5v


volatile unsigned max_current_ref = 0;			// max_current_ref in variable so controlled by temperature
volatile unsigned current_ref = 0;
volatile unsigned long battery_amp_units = 0;			// calculated battery AH used by controller
volatile unsigned int battery_amp_hours = 0;

volatile unsigned throttle_fault_counts = 0;
volatile unsigned char fault_bits = PRECHARGE_FAULT;

char dataArray[128];  // = ; //Use this for saving the text that you want outputted to the Serial port.  {'I','a','=','x','x','x',0x0D,0x0A,

void InitIORegisters();
void clear_oc();

void __attribute__ ((__interrupt__)) _ADCInterrupt(void);
void InitUART2(void);
void CalcRefVec(void);
void GetRotorFluxAnglePMSM();
void ComputeSpeedACIM();


int main() {
	int counter1=0;

	InitIORegisters(); // Now the interrupt is running...
//	PRECHARGE_RELAY = 0;	// low turns on the precharge relay.
	clear_oc();	// It starts in unknown state. So, clear overcurrent.	

	InitUART2();

	while(1) {
	//	if (fault_bits & PRECHARGE_FAULT) {
	//		if (counter_1k >= 8000) { // 8 seconds
	//			fault_bits &= ~PRECHARGE_FAULT;  // clear the precharge fault.
	//			CONTACTOR_RELAY = 0; // close main contactor.
	//			PRECHARGE_RELAY = 1; // open the precharge relay. It should be basically 0 current, so OK to open.
	//		}
 	//	}
		// now that horror is behind us.
							
//		 Now, analyze the fault bits, to see what to do!
	//	if (fault_bits) {
	//		if (fault_bits & VREF_FAULT) {	// This is really really bad.  Probably no hardware current limiting.  Just open contactors even if a lot of current is flowing through.  Contactor damage is worth it.
	//			CONTACTOR_RELAY = 1;
	//			PRECHARGE_RELAY = 1;
	//		}
	//		else if (fault_bits & THROTTLE_FAULT) {
	//			if (current_feedback < 10) { // make sure the current has fallen to no more than a small amount of amps before opening the contactors.  No sense messing up the contacts.
	//				CONTACTOR_RELAY = 1;
	//				PRECHARGE_RELAY = 1;
	//			}
	//		}
	//	}
		
		dataArray[0] = overCurrentHasOccurred;
		dataArray[1] = i_a >> 2; // in [-128, 128] or so
		dataArray[2] = i_b >> 2; // in [-128, 128] or so.
		dataArray[3] = i_c >> 2; // in [-128, 128]
		dataArray[4] = //i_d;
		dataArray[5] = //i_q; 
		dataArray[6] = throttle_feedback >> 3; // in [-2047, 2047], so divide by 8 to get it in [-127, 127].  You will wna tto see later if i_q is tracking throttle, and i_q is in [-127, 127]
		dataArray[7] = duty1 >> 3;//smallSpeed_V_HZ >> 2); // smallSpeed_V_HZ >> 2 should be in [-127, 127] if it's in -60 Hz to 60 Hz.  This is the speed I am commanding.  The rate for the V/Hz method.
		dataArray[8] = duty2 >> 3;//rotorSpeed >> 2; // in [-128, 128]
		dataArray[9] = duty3 >> 3;//rotorFluxAngle >> 2;	// in [0, 255]
		dataArray[10] = //rotorFluxAngle & 0b11; // now the lower 2 bits too.  Don't lose those.  You want an accurate reading of the rotor offset.
		dataArray[11] = throttle_feedback >> 3;//rotorPos;  // This is the variable that you want to find!
		
		now = counter_8k;
		if (now - previous > 16383) {
			if (TransmitReady()) {
				SendCharacter(dataArray[counter1++]);
				if (counter1 > 11) {
					counter1 = 0;
					previous = now;
				}
			}
		}
		asm("CLRWDT");
	}
	return 0;
}

void InitIORegisters() {
	// It takes less power to pull a port high than to pull it low.
	// See Pg. 183 of dsPIC30F4011 pdf.
	// So, I think it's better to have the ports connected to ground through a resistor.  That is 0v solid.
	// RD0 = contactor coil.
	// RD2 = precharge relay.
	// RE8 = output LED.
	_TRISD0 = 0;  // Output for contactor relay #1 
	CONTACTOR_RELAY = 1;  // MAKE SURE IT'S HIGH.  OFF

	_TRISD2 = 0;  // Output for precharge relay
	PRECHARGE_RELAY = 1;  // MAKE SURE IT'S HIGH.  OFF

	_TRISE8 = 0;   // Output for status LED
	STATUS_LED = 0; // status led starts on.

	_TRISD3 = 0;   // Output for over current trip reset.
	OVER_CURRENT_TRIP_RESET = 1;
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	OVER_CURRENT_TRIP_RESET = 0;  // bring it low
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	asm("nop"); asm("nop");	asm("nop"); asm("nop");
	OVER_CURRENT_TRIP_RESET = 1; // reset overcurrent

	_TRISD1 = 1;  // Set the pin up as an INPUT.  overcurrent trip state.  Has an overcurrent event happened?
	// You can't set OVER_CURRENT_TRIP_STATE to anything, since it's an input!  HAHA.
	// OVER_CURRENT_TRIP_STATE is 0 if NO overcurrent event has occurred.  It is 1 if an overcurrent event HAS happened.
	

// ============= TIMER #1 ======================
    PR1 = 0xFFFF; // See Pg. 70 in 30f40ll documentation.  It starts as 0xFFFF by default anyway.  Period Register 1.

	// The timer will run at 2Mhz???  Why would I do that?
	T1CON = 0x8010; // 0b1000000000010000.  See pg. 269 in the Family Reference Manual.
				// TON = 1; Start timer 1.
					// TSIDL = 0; Continue to operate in idle mode.
					// TGATE = 0; Gated time accumulation disabled.  What does that mean?!
					// TCKPS = 01; 1:8 prescale value.  Why???
					// TSYNC = 0; Since TCS = 0 in this case, this bit is ignored.
					// TCS = 0; Internal clock (FOSC/4). 

// ============= Motor PWM ======================

    PTCONbits.PTSIDL = 0;// = 0b1000000000000010;         // Pg. 337 in FRM.  Enable PWM for center aligned operation.
	PTCONbits.PTOPS = 0;
	PTCONbits.PTCKPS = 0;
	PTCONbits.PTMOD = 0b10;
	// ENABLE THE TIME BASE at the end.

							// PTCON = 0b1000000000000010;  Pg. 337 in Family Reference Manual.
							// PTEN = 1; PWM time base is ON
							// PTSIDL = 0; PWM time base runs in CPU Idle mode
							// PTOPS = 0000; 1:1 Postscale
							// PTCKPS = 00; PWM time base input clock period is TCY (1:1 prescale)
							// PTMOD = 10; PWM time base operates in a continuous up/down counting mode
    PTPERbits.PTPER = 1024;//dPWMPeriodInTcy/2;	// Time base period register.  PTPER == 1024 in this case, since it's running at about 8KHz or so.

    // SEVTCMP: Special Event Compare Count Register 
    // Phase of ADC capture set relative to PWM cycle: 0 offset and counting up
	// 
    SEVTCMPbits.SEVTDIR = 0;  
	SEVTCMPbits.SEVTCMP = 3;
						// SEVTCMP cannot be 0 -> turns off trigger (Missing from doc)
						// SEVTCMP = 0b0000000000000011;  Pg. 339 in Family Reference Manual.
						// SEVTDIR = 0; A special event trigger will occur when the PWM time base is counting upwards and...
						// SEVTCMP = 000000000000010; If SEVTCMP == PTMR<14:0>, then a special event trigger happens.

	PWMCON1bits.PMOD1 = 1;	// Pg. 339 in FRM.
	PWMCON1bits.PMOD2 = 1;
	PWMCON1bits.PMOD3 = 1;

	PWMCON1bits.PEN1H = 1;
	PWMCON1bits.PEN2H = 1;
	PWMCON1bits.PEN3H = 1;

	PWMCON1bits.PEN1L = 1;
	PWMCON1bits.PEN2L = 1;
	PWMCON1bits.PEN3L = 1;

							// run in complementary output mode.
							// PEN3H = PEN2H = PEN1H = 1;  See Pg. 339 in Family Reference Manual. 
							// PEN3L = 1   PEN2L = 1   PEN1L = 1;  1 means enable that pwm channel.

	PWMCON2bits.SEVOPS = 0;
	PWMCON2bits.IUE = 0;
	PWMCON2bits.OSYNC = 0;
	PWMCON2bits.UDIS = 0;

	DTCON1bits.DTAPS = 0b11; // Prescaler of 8.  
	DTCON1bits.DTA = 32; // 32 clock cycles.  Maximum number of clock cycles for the deadtime is 63.  deadtime in this case is prescaler*32 Tcy periods.  That works out to 16uS of deadtime if 1 Tcy is 1/16 000 000 sec.

//    FLTACON = 0;            // Pg. 343 in Family Reference Manual.  What to do when something happens on FAULT pin.  Nothing in this case.
							// I'm not using the fault pin.
	//OVDCON = ;

    PDC1 = 0; // like OCR1A for the ATMega8.  16 bit value.  The PWM Duty for channel 1.
	PDC2 = 0; // PWM Duty for channel 2.
	PDC3 = 0; // PWM Duty for channel 3.
    // Center aligned PWM.  Oh heck ya.  It won't sample the A/D channels until the center of the ON time of the pwm, so no switching will happen while sampling, which cuts down on noise.

	PTCONbits.PTEN = 1;


// ============= ADC - Measure current 1, current 2, current 3, Throttle, temperature.
// ADC setup for simultanous sampling on 
//      CH0=, CH1=, CH2=, CH3=AN??. 
// AN0 = CURRENT 1
// AN1 = CURRENT 2
// AN2 = CURRENT 3
// AN6 = THROTTLE
// AN7 = TEMPERATURE
// Sampling triggered by PWM 

	// Note:  F.R.M. means Family Resource Manual for the dsPIC30F family of microcontrollers.
   
    ADCON1bits.FORM = 0;  // If FORM == 3, THE FORM WILL BE 1.15.  I'm not using that though. I'm doing unsigned int, since I'm doing fixed point math instead.
    // Motor Control PWM interval ends sampling and starts conversion
    ADCON1bits.SSRC = 3;  

    // Simultaneous Sample Select bit (only applicable when CHPS = 01 or 1x)
    // Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
    // Samples CH0 and CH1 simultaneously (when CHPS = 01)
    ADCON1bits.SIMSAM = 1; 
 
    // Sampling begins immediately after last conversion completes. 
    // SAMP bit is auto set.
    ADCON1bits.ASAM = 1;  

    // Pg. 407 in F.R.M.
    // Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
    ADCON2bits.CHPS = 2; // VCFG = 000; This selects the A/D High voltage as AVdd, and A/D Low voltage as AVss.
						 // SMPI = 0000; This makes an interrupt happen every time the A/D conversion process is done (for all 4 I guess, since they happen at the same time.)
						 // ALTS = 0; Always use MUX A input multiplexer settings
						 // BUFM = 0; Buffer configured as one 16-word buffer ADCBUF(15...0)

    // Pg. 408 in F.R.M.
    // A/D Conversion Clock Select bits = 8 * Tcy
    ADCON3bits.ADCS = 15;  // 

    // ADCHS: ADC Input Channel Select Register 
    // Pg. 409 in F.R.M.
    // CH0 positive input is AN6.  AN6 is throttle.
    ADCHSbits.CH0SA = 6;
    	
	// CH1 positive input is AN0, CH2 positive input is AN1, CH3 positive input is AN2.
	ADCHSbits.CH123SA = 0;

	// CH0 negative input is Vref-.
	ADCHSbits.CH0NA = 0;

	// CH1, CH2, CH3 negative inputs are Vref-, which is AVss, which is Vss.  haha.
    ADCHSbits.CH123NA = 0;

    // ADPCFG: ADC Port Configuration Register 
    // Pg. 410 F.R.M.
	// Use AN0, AN1, AN2, and AN6  as the A/D inputs.  So, set PCFG0, PCFG1, PCFG2 and PCFG6 to 0.  All other pins should be digital, so set them to 1. 
    ADPCFGbits.PCFG0 = 0;   // AN0 analog: current 1
    ADPCFGbits.PCFG1 = 0;   // AN1 analog: current 2
    ADPCFGbits.PCFG2 = 0;   // AN2 analog: current 3
    ADPCFGbits.PCFG3 = 1;   
    ADPCFGbits.PCFG4 = 1;   
    ADPCFGbits.PCFG5 = 1;   
    ADPCFGbits.PCFG6 = 0;   // AN6 analog: Throttle
    ADPCFGbits.PCFG7 = 1;   // AN7 analog: Temperature.  Change back to 0 later.
    ADPCFGbits.PCFG8 = 1;   


    // ADCSSL: ADC Input Scan Select Register 
	// This makes no sense to me.
    //ADCSSL = 0; // Pg. 410 F.R.M.
	// I think it sets the order that the A/D inputs are done.  But I'm doing 4 all at the same time, so set it to 0?

    // Turn on A/D module
    ADCON1bits.ADON = 1; // Pg. 416 in F.R.M.  Under "Enabling the Module"
						 // ** It's important to set all the bits above before turning on the A/D module. **
						 // Now the A/D conversions start happening once ADON == 1.
	IEC0bits.ADIE = 1;	 // Enable interrupts to happen when a A/D conversion is complete. Pg. 148 of F.R.M.  


	return;
}

//---------------------------------------------------------------------
// The ADC sample and conversion is triggered by the PWM period.
//---------------------------------------------------------------------
// This will happen at a frequency of about 7.8 khz.
void __attribute__ ((__interrupt__)) _ADCInterrupt(void) {
    IFS0bits.ADIF = 0;  	// Interrupt Flag Status Register. Pg. 142 in F.R.M.
							// ADIF = A/D Conversion Complete Interrupt Flag Status bit.  
							// ADIF = 0 means we are resetting it so that an interrupt request has not occurred.
	counter_8k++;
	if ((counter_8k & 7) == 0) {  // 
		if (OVER_CURRENT_TRIP_STATE == 1) {// if an overcurrent event has occurred...
			overCurrentHasOccurred = 1; 	
			clear_oc();
		}
	}

// V/Hz section ///////////////////////////////////////////////////////////////
//	smallSpeed_V_HZ = (int)(speed_V_HZ >> 16);
//	if (smallSpeed_V_HZ < throttle_average) // throttle_average is in [0, 2047].
//		speed_V_HZ += 8192L;
//	else if (smallSpeed_V_HZ > throttle_average)  
//		speed_V_HZ -= 8192L;

	// now, to shift to [0, 511]. 
//	smallSpeed_V_HZ = (int)(speed_V_HZ >> 18);
//	if (smallSpeed_V_HZ > 511)	// clamp it so PDC1, 2, and 3 aren't too big or too small.
//		smallSpeed_V_HZ = 511;
//	else if (smallSpeed_V_HZ < -511)
//		smallSpeed_V_HZ = -511;
	// Move to the next part in the sin table.
//	positionHiResPH1 += smallSpeed_V_HZ;  // positionHiResPH1 is in [0, 65535]. smallSpeed_V_HZ of 511 corresponds to about 60 Hz.

	positionHiResPH1 += (throttle_feedback >> 3);  // positionHiResPH1 is in [0, 65535]. smallSpeed_V_HZ of 511 corresponds to about 60 Hz.
	
	
	positionHiResPH2 = positionHiResPH1 + 0x5555; // 120 degree offset.  Who cares if it overflows.  It just wraps around.  Heck ya.
	positionHiResPH3 = positionHiResPH1 + 0xAAAA; // 240 degree offset.  Heck ya.  That's what I'm talking about.  This is exciting...
	
	sinPhase1 = _sin[positionHiResPH1 >> 7];  // (positionHiResPH1 >> 7) is in [0, 511].  sinPhase1 is in [-32767, 32767].  32767 corresponds to 1, or so.  crap. pretend that 1 corresponds to 32768.
	sinPhase2 = _sin[positionHiResPH2 >> 7];  // 
	sinPhase3 = _sin[positionHiResPH3 >> 7];

	// the 3 duty cycle generators. 
//	if (throttle_feedback > 512) { 
//		duty1 = ((((long)throttle_feedback)   *   sinPhase1) >> 24) + 1024; // [-512, 512]*[-32768, 32768] is safely in [-2^24+1, 2^24-1].  First I want the result in the range [-2^10, 2^10].  So I must shift from 2^24 to 2^10, so down by 14.	
//		duty2 = ((((long)throttle_feedback)   *   sinPhase2) >> 24) + 1024; // [-512, 512]*[-32768, 32768] is safely in [-2^24+1, 2^24-1].  First I want the result in the range [-2^10, 2^10].  So I must shift from 2^24 to 2^10, so down by 14.	
//		duty3 = ((((long)throttle_feedback)   *   sinPhase3) >> 24) + 1024; // [-512, 512]*[-32768, 32768] is safely in [-2^24+1, 2^24-1].  First I want the result in the range [-2^10, 2^10].  So I must shift from 2^24 to 2^10, so down by 14.	
//	}

	if (throttle_feedback > 0) {
		duty1 = (sinPhase1 >> 5) + 1024; // [-512, 512]*[-32768, 32768] is safely in [-2^24+1, 2^24-1].  First I want the result in the range [-2^10, 2^10].  So I must shift from 2^24 to 2^10, so down by 14.	
		duty2 = (sinPhase2 >> 5) + 1024; // [-512, 512]*[-32768, 32768] is safely in [-2^24+1, 2^24-1].  First I want the result in the range [-2^10, 2^10].  So I must shift from 2^24 to 2^10, so down by 14.	
		duty3 = (sinPhase3 >> 5) + 1024; // [-512, 512]*[-32768, 32768] is safely in [-2^24+1, 2^24-1].  First I want the result in the range [-2^10, 2^10].  So I must shift from 2^24 to 2^10, so down by 14.	
	}
	else {
		duty1 = 0;
		duty2 = 0;
		duty3 = 0;
	}

	PDC1 = duty1;
	PDC2 = duty2;
	PDC3 = duty3; 
///////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////
// Measuring throttle, and other stuff
	if ((counter_8k & 0x03) == 0x03) {	// 2khz
		counter_2k++;

		if ((counter_2k & 0x7FF) == 0x7FF) { // 
			counter_1sec++;  // this happens every second.
		 	if (STATUS_LED == 0)  // toggle the LED.
				STATUS_LED = 1;
			else STATUS_LED = 0;
		}

		if ((counter_2k & 0x01) == 0x00) {  // 1kHz
			counter_1k++;
			throttle_feedback = ADCBUF0;  // throttle is on AN6, which obviously is ADCBUF0.  hahahahaha.

			if (throttle_feedback > THROTTLE_MAX_RAW) // clamp it to allow some dead zone.
				throttle_feedback = THROTTLE_MAX_RAW;
			else if (throttle_feedback < THROTTLE_MIN_RAW)
				throttle_feedback = THROTTLE_MIN_RAW;
			throttle_feedback -= THROTTLE_MIN_RAW;
			// now throttle_feedback is in [0, THROTTLE_RANGE_RAW], but 0 means max throttle.  So, invert it!

			throttle_feedback = THROTTLE_RANGE_RAW - throttle_feedback;
			// now, 0 throttle is 0 and max throttle is THROTTLE_RANGE_RAW
			
			throttle_feedback = (((long)throttle_feedback) << 11) / (long)(THROTTLE_RANGE_RAW);
		}
	}
}

void clear_oc(void)
{
	OVER_CURRENT_TRIP_RESET = 0;				// OC clear low (low to clear)
	asm("nop"); asm("nop");				// 4 nops = 1/4th uS - enough for 74HC00
	asm("nop"); asm("nop"); 
	asm("nop"); asm("nop");				// 4 nops = 1/4th uS - enough for 74HC00
	asm("nop"); asm("nop"); 
	asm("nop"); asm("nop");				// 4 nops = 1/4th uS - enough for 74HC00
	asm("nop"); asm("nop"); 
	asm("nop"); asm("nop");				// 4 nops = 1/4th uS - enough for 74HC00
	asm("nop"); asm("nop"); 
	OVER_CURRENT_TRIP_RESET = 1;				// OC clear high (high for normal operation)
}
